#include "project/initialization.h"

void
loadPly(char* file_name, int* num_vertices, int* num_faces, Vertex*** external_vlist, Face*** external_flist)
{
	// Lista de informacoes de propriedades para vertices
	// OBS.: nos poderiamos ter alocado dinamicamente esta estrutura
	PlyProperty vert_props[] = { 
		{"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,x), 0, 0, 0, 0},
		{"y", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,y), 0, 0, 0, 0},
		{"z", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,z), 0, 0, 0, 0},
	};

	// Lista de informacoes de propriedades para faces
	PlyProperty face_props[] = { 
		{"intensity", PLY_UCHAR, PLY_UCHAR, offsetof(Face,intensity), 0, 0, 0, 0},
		{"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
		1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
	};

	PlyFile *ply = NULL;
	PlyProperty **plist = NULL;
	PlyElement *pelem = NULL;
	Vertex** vlist = NULL;
	Face** flist = NULL;
	int i, j, k;
	int nelems = 0;
	int num_elems = 0;
	int nprops = 0;
	char **elist = NULL;
	int file_type = 0;
	float version = 0.0;

	ply = ply_open_for_reading(file_name, &nelems, &elist, &file_type, &version);
	if (!ply)
	{
		fprintf(stderr, "ply_open_for_reading: error opening ply file\n");
		exit(-1);
	}

	for (i = 0; i < nelems; i++)
	{
		// Obtem lista de propriedades sobre o elemento atual
		plist = ply_get_element_description(ply, elist[i], &num_elems, &nprops);

		if ( !strcmp("vertex", elist[i]) )
		{
			// Dereferencia o ponteiro passado como parametro sobre a quantidade total de elementos vertices
			*num_vertices = num_elems;
	                
			// Cria uma lista para armazenar todos os vertices
			vlist = (Vertex **) calloc (num_elems, sizeof(Vertex *));

			if (!vlist)
			{
				fprintf(stderr, "initPly: error allocating memory for vertex list\n");
				exit(-1);
			}  
 			*external_vlist = vlist;

			ply_get_property (ply, elist[i], &vert_props[0]);
			ply_get_property (ply, elist[i], &vert_props[1]);
			ply_get_property (ply, elist[i], &vert_props[2]);
	
			// Obtem todos os vertices 
			for (j = 0; j < num_elems; j++) 
			{
				// Obtem um vertice do arquivo e o armazena em uma das estruturas do vetor alocado
	                	vlist[j] = (Vertex *) calloc (1, sizeof (Vertex));
				if (!vlist)
				{
					fprintf(stderr, "initPly: error allocating memory for vertex list\n");
					exit(-1);
				}
	
				ply_get_element (ply, (void *) vlist[j]);
			}
		}

		if ( !strcmp("face", elist[i]) ) 
		{
			*num_faces = num_elems; 
	                 
			// Cria uma lista para armazenar todos as faces
			flist = (Face **) calloc (num_elems, sizeof (Face *));

			if (!flist)
			{
				fprintf(stderr, "initPly: error allocating memory for face list\n");
				exit(-1);
			}
			*external_flist = flist;
	
			ply_get_property (ply, elist[i], &face_props[0]);
			ply_get_property (ply, elist[i], &face_props[1]);
	
			// Obtem todas as faces
			for (j = 0; j < num_elems; j++) 
			{
				// Obtem um vertice do arquivo e o armazena em uma das estruturas do vetor alocado
				flist[j] = (Face *) calloc (1, sizeof (Face));
				if (!flist)
				{
					fprintf(stderr, "initPly: error allocating memory for face list\n");
					exit(-1);
				}
	
				ply_get_element (ply, (void *) flist[j]);
			}
		}
	}
	ply_close(ply);
}
